package com.bestom.waterquality.services;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;

import androidx.core.app.NotificationCompat;

import com.bestom.waterquality.R;
import com.bestom.waterquality.WaterQualityApplication;
import com.bestom.waterquality.entity.Constant;
import com.bestom.waterquality.entity.DataEntity;
import com.bestom.waterquality.entity.IoChangeBean;
import com.bestom.waterquality.entity.NodeBean;
import com.bestom.waterquality.listener.IGetMessageCallBack;
import com.bestom.waterquality.logic.IOSet;
import com.bestom.waterquality.logic.RelaySet;
import com.bestom.waterquality.util.DataTurn;
import com.bestom.waterquality.util.FastJsonUtil;
import com.bestom.waterquality.util.ImageUtil;
import com.bestom.waterquality.util.SharedPreferencesUtil;

import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

public class MQTTService2 extends Service {

    public static final String TAG = MQTTService2.class.getSimpleName();

    public static MqttAndroidClient client;
    private MqttConnectOptions conOpt;
    private static IGetMessageCallBack IGetMessageCallBack;
    private static Context mContext;
    private static String mTopic;
    private static String mHost;
    private static String mPort;
    private static String mClientId;
    private static String mUser;
    private static String mPassword;
    private static SimpleDateFormat sDateFormat;

    @Override
    public void onCreate() {
        super.onCreate();
        init();
        sDateFormat = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
    }

    /**
     * @param topic 发布主题
     * @param type 类型，01 实时   02 警告
     * @param value 数据值
     * @param imagePath 图片路径
     */
    public static void publish(String topic, String type, String value, String imagePath){

        DataTurn mDataTurn = new DataTurn();
        // 读取图像设置功能中保存的信息，用于添加水印
        String sf = (String) SharedPreferencesUtil.getInstance().getValue(Constant.imageSet,"false-0-0-0");
        String[] strings = sf.split("-");
        Log.d(TAG,"imagePath:" + imagePath);
        // 存储图片字节
        byte[] imageByte = null;
        // 如果图片路径不为空，做以下加水印信息等操作
        if (!imagePath.isEmpty()){
            String[] split = imagePath.split("/");
            String time = sDateFormat.format(new Date(Long.parseLong(split[split.length-1].split("\\.")[0])));
            String watermark = "";
            if (strings[0].equals("false")){//显示ID开关是否打开
                watermark += value + "\n" + time;
            }else {
                watermark += Constant.defDeviceId + "\n" + value + "\n" + time;
            }
            int size = 50;
            switch (strings[1]){//字体大小
                case "0":
                    size = 50;
                    break;
                case "1":
                    size = 40;
                    break;
                case "2":
                    size = 30;
                    break;
                case "3":
                    size = 60;
                    break;
                case "4":
                    size = 70;
                    break;
                case "5":
                    size = 80;
                    break;
            }

            int color = Color.RED;
            switch (strings[2]){//字体颜色
                case "0":
                    color = Color.RED;
                    break;
                case "1":
                    color = Color.YELLOW;
                    break;
                case "2":
                    color = Color.BLUE;
                    break;
                case "3":
                    color = Color.GREEN;
                    break;
            }

            Bitmap bitmap = ImageUtil.getInstance().getImage(imagePath);

            if (bitmap != null){
                switch (strings[3]){//水印位置
                    case "0": // 左上
                        imageByte = mDataTurn.Bitmap2Bytes(ImageUtil.getInstance().drawTextToLeftTop(mContext, bitmap, watermark, size, color, 44, 110));
                        break;
                    case "1": // 左下
                        imageByte = mDataTurn.Bitmap2Bytes(ImageUtil.getInstance().drawTextToLeftBottom(mContext, bitmap, watermark, size, color, 44, 170));
                        break;
                    case "2": // 正中
                        imageByte = mDataTurn.Bitmap2Bytes(ImageUtil.getInstance().drawTextToCenter(mContext, bitmap, watermark, size, color));
                        break;
                    case "3": // 右上
                        imageByte = mDataTurn.Bitmap2Bytes(ImageUtil.getInstance().drawTextToRightTop(mContext, bitmap, watermark, size, color, 44, 70));
                        break;
                    case "4": // 右下
                        imageByte = mDataTurn.Bitmap2Bytes(ImageUtil.getInstance().drawTextToRightBottom(mContext, bitmap, watermark, size, color, 44, 170));
                        break;
                }
            }
        }

        DataEntity dataEntity = new DataEntity(mClientId, type, transform("yyyyMMddHHmmss", System.currentTimeMillis()), "0", value, imageByte);

        String msg = FastJsonUtil.objectToJsonForFastJson(dataEntity);
        try {
            if (client != null){
                client.publish(topic, msg.getBytes(), 0, false);
                Log.i(TAG, "publish topic-->" + topic + "  msg-->" + msg);
            }
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    public static void publish(String topic, NodeBean bean){

        String msg = FastJsonUtil.objectToJsonForFastJson(bean);
        try {
            if (client != null){
                client.publish(topic, msg.getBytes(), 0, false);
                Log.i(TAG, "publish topic-->" + topic + "  msg-->" + msg);
            }
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }
    public static void publish(String topic, String ioId, String status){

        IoChangeBean bean = new IoChangeBean(mClientId, transform("yyyyMMddHHmmss", System.currentTimeMillis()), ioId, status);
        String msg = FastJsonUtil.objectToJsonForFastJson(bean);
        try {
            if (client != null){
                client.publish(topic, msg.getBytes(), 0, false);
                Log.i(TAG, "publish topic-->" + topic + "  msg-->" + msg);
            }
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    /**set time format*/
    private static String transform(String pattern, long msec) {
        return new SimpleDateFormat(pattern).format(msec);
    }

    private void init() {
        // 服务器地址（协议+地址+端口号）
        client = new MqttAndroidClient(this, "tcp://" + mHost + ":" + mPort, mClientId);
        // 设置MQTT监听并且接受消息
        client.setCallback(mqttCallback);

        conOpt = new MqttConnectOptions();
        // 清除缓存
        conOpt.setCleanSession(true);
        // 设置超时时间，单位：秒
        conOpt.setConnectionTimeout(10);
        // 心跳包发送间隔，单位：秒
        conOpt.setKeepAliveInterval(20);
        // 用户名
        conOpt.setUserName(mUser);
        // 密码
        conOpt.setPassword(mPassword.toCharArray());

        // last will message
        boolean doConnect = true;
        String message = "{" + "\"" + mClientId + "Device\":\"" + "close" + "\"}";
        Log.e(getClass().getName(), "message是:" + message);

        if ((!message.equals("")) || (!mTopic.equals(""))) {
            // 最后的遗嘱
            // MqTT本身就是为信号不稳定的网络设计的，所以难免一些客户端会无故的和Broker断开连接。
            //当客户端连接到Broker时，可以指定LWT，Broker会定期检测客户端是否有异常。
            //当客户端异常掉线时，Broker就往连接时指定的topic里推送当时指定的LWT消息。
            try {
                conOpt.setWill(mTopic, message.getBytes(), 0, false);
            } catch (Exception e) {
                Log.i(TAG, "Exception Occured", e);
                doConnect = false;
                iMqttActionListener.onFailure(null, e);
            }
        }

        if (doConnect) {
            doClientConnection();
        }
    }

    @Override
    public void onDestroy() {
        Log.i(TAG, "onDestroy!!");
        stopSelf();
        try {
            client.disconnect();
        } catch (MqttException e) {
            e.printStackTrace();
        }
        super.onDestroy();
    }

    /** 连接MQTT服务器 */
    private void doClientConnection() {
        if (!client.isConnected() && isConnectIsNormal()) {
            try {
                client.connect(conOpt, null, iMqttActionListener);
            } catch (Exception e) {
                e.printStackTrace();
                if (IGetMessageCallBack != null){
                    IGetMessageCallBack.setFail("2", "fail");
                }
            }
        }
    }

    /**MqTT是否连接成功*/
    private final IMqttActionListener iMqttActionListener = new IMqttActionListener() {

        @Override
        public void onSuccess(IMqttToken arg0) {
            Log.i(TAG, "连接成功 ");
            try {
                IGetMessageCallBack.setSuccess("2", "success");
                // 订阅myTopic话题
                client.subscribe(Constant.DataSubscribeTopic,1);
                client.subscribe(Constant.DataImageSubscribeTopic,1);
                client.subscribe(Constant.UpgradeSubscribeTopic,1);
                client.subscribe(Constant.IoSubscribeTopic,1);
                client.subscribe(Constant.RelaySubscribeTopic,1);
                client.subscribe(Constant.IoStateChangesSubscribeTopic,1);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(IMqttToken arg0, Throwable arg1) {
            arg1.printStackTrace();
            // 连接失败，重连
            IGetMessageCallBack.setFail("2", "fail");
            mHandler.postDelayed(mRunnable,10000);
        }
    };

    private final Handler mHandler = new Handler();
    private final Runnable mRunnable = this::doClientConnection;

    /**MqTT监听并且接受消息*/
    private final MqttCallback mqttCallback = new MqttCallback() {

        @Override
        public void messageArrived(String topic, MqttMessage message) throws Exception {

            String str1 = new String(message.getPayload());

            Log.i(TAG, "messageArrived:" + str1);
            if (topic.equals(Constant.RelaySubscribeTopic)){
                NodeBean nodeBean = FastJsonUtil.jsonToObjectForFastJson(str1, NodeBean.class);
                Log.d(TAG, nodeBean.toString());
                RelaySet.getInstance().setValue(nodeBean.getRelayId(), nodeBean.getSet());
            }else if (topic.equals(Constant.IoSubscribeTopic)){
                NodeBean nodeBean = FastJsonUtil.jsonToObjectForFastJson(str1, NodeBean.class);
                Log.d(TAG, nodeBean.toString());
                IOSet.getInstance().setValue(nodeBean.getRelayId(), nodeBean.getSet());
            }else if (topic.equals(Constant.UpgradeSubscribeTopic)){
                Log.i(TAG, "UpgradeSubscribeTopic  messageArrived:" + str1);
            }else {
                Log.i(TAG, "topic:" + topic + "  messageArrived:" + str1);
            }

        }

        @Override
        public void deliveryComplete(IMqttDeliveryToken arg0) {

        }

        @Override
        public void connectionLost(Throwable arg0) {
            // 失去连接，重连
            // doClientConnection();
            IGetMessageCallBack.setFail("2", "fail");
        }
    };

    /** 判断网络是否连接 */
    private boolean isConnectIsNormal() {
        ConnectivityManager connectivityManager = (ConnectivityManager) this.getApplicationContext()
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = connectivityManager.getActiveNetworkInfo();
        if (info != null && info.isAvailable()) {
            String name = info.getTypeName();
            Log.i(TAG, "MQTT当前网络名称：" + name);
            return true;
        } else {
            Log.i(TAG, "MQTT 没有可用网络");
            IGetMessageCallBack.setFail("2", "net");
            /*没有可用网络的时候，延迟10秒再尝试重连*/
            if (WaterQualityApplication.mt2IsOk) mHandler.postDelayed(mRunnable, 10000);
            return false;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.e(getClass().getName(), "onBind");
        return new CustomBinder();
    }

    public static void setConnectInfo(Context context, String topic, String host, String port, String clientId, String user, String password, IGetMessageCallBack mIGetMessageCallBack){
        mContext = context;
        mTopic = topic;
        mHost = host;
        mPort = port;
        mClientId = clientId;
        mUser = user;
        mPassword = password;
        IGetMessageCallBack = mIGetMessageCallBack;
    }

    public class CustomBinder extends Binder {
        public MQTTService2 getService(){
            return MQTTService2.this;
        }
    }

    public  void toCreateNotification(String message){
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, new Intent(this, MQTTService2.class), PendingIntent.FLAG_UPDATE_CURRENT);
        //3、创建一个通知，属性太多，使用构造器模式
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);

        Notification notification = builder
                .setTicker("测试标题")
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("")
                .setContentText(message)
                .setContentInfo("")
                .setContentIntent(pendingIntent)  // 点击后才触发的意图，“挂起的”意图
                .setAutoCancel(true)              // 设置点击之后notification消失
                .build();
        NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        startForeground(0, notification);
        notificationManager.notify(0, notification);

    }
}